<template>
  <LabelPrefixWraper
    v-show="mappingProps.visible"
    :label="mappingProps.label"
    :hideLabel="mappingProps.hideLabel"
    :labelPosition="mappingProps.labelPosition"
    :helpConf="mappingProps.helpConf"
    :helpTooltip="mappingProps.helpTooltip"
    :helpPlacement="mappingProps.helpPlacement"
    :helpMore="mappingProps.helpMore"
    :helpMorePopup="mappingProps.helpMorePopup"
    :helpMoreLink="mappingProps.helpMoreLink"
    :helpMoreLinkHrefStatic="mappingProps.helpMoreLinkHrefStatic"
    :helpMoreLinkHrefExp="mappingProps.helpMoreLinkHrefExp"
    :required="mappingProps.required"
  >
    <div
      class="t-chips-full-width"
      :style="mappingProps.hideLabel ? {} : { maxWidth: 'calc(100% - 80px)' }"
    >
      <div ref="refComponent" class="t-chips" v-show="mappingProps.visible">
        <!-- 注意此处，
          v-bind 之前的属性，为本组件确认的chip默认样式效果值，低代码未暴露属性
          v-bind 之后的属性，为低代码中暴露的属性（label=''是为了覆盖默认字段）
        -->
        <form class="t-chips-wrap" @submit="handleSubmit">
          <template v-if="inDesign">
            <Chip
              v-for="(item, index) of [
                { TagName: '标签-动态数据源1' },
                { TagName: '标签-动态数据源2' },
              ]"
              :key="item.TagName"
              :class="inDesign ? 'in-disgin' : ''"
              dense
              v-bind="{
                ...attrs,
                ...{ class: null, style: null, id: null },
                ...mappingProps,
              }"
              label=""
              :clickable="mappingProps.clickable"
              :removable="
                !mappingProps.readonly &&
                (!isMobile ? true : item.removableForXs)
              "
              :modelValue="true"
              :tabIndex="mappingProps.tabIndex"
            >
              <slot>
                <span class="tag-name" :title="item.TagName">{{
                  item.TagName
                }}</span>
              </slot>
            </Chip>
          </template>
          <Chip
            v-for="(item, index) of mappingProps.modelValue || []"
            :key="item.TagName"
            dense
            v-bind="{
              ...attrs,
              ...{ class: null, style: null, id: null },
              ...mappingProps,
            }"
            class="chip"
            :class="[
              isMobile ? 'chip-mobile' : 'chip-pc',
              !!Number(mappingProps.selfClickable)
                ? 'chip-self-clickable-true'
                : 'chip-self-clickable-false',
            ]"
            label=""
            :clickable="mappingProps.clickable"
            :selfClickable="!!Number(mappingProps.selfClickable)"
            :removable="
              !mappingProps.readonly && (!isMobile ? true : item.removableForXs)
            "
            :modelValue="true"
            @click="handleClickChip(item)"
            @remove="handleRemove(item)"
            @keyup.enter="handleEnter(item)"
            :tabIndex="mappingProps.tabIndex"
            :tabIndexIconRemove="tabIndexIconRemove"
          >
            <slot>
              <span class="tag-name" :title="item.TagName">{{
                item.TagName
              }}</span>
            </slot>
          </Chip>
          <!-- t-input
            outlined/borderless/standout/filled => 这个存在属性，改为
            borderType='outlined/borderless/standout/filled' -->
          <Input
            v-model="msg"
            class="t-chips-input"
            type="text"
            dense
            borderType="borderless"
            :hideLabel="true"
            :placeholder="mappingProps.placeholder"
            :readonly="mappingProps.readonly"
            @blur="handleBlur"
            @focus="handleFocus(msg)"
            :tabIndex="mappingProps.tabIndex"
            :tabIndexIconRemove="tabIndexIconRemove"
          />
        </form>
        <ul
          v-show="!!actions.length"
          class="data-source-list"
          :style="isDropDown ? listTopStyle : listDownStyle"
        >
          <li
            v-for="(item, index) of actions"
            :key="item"
            class="data-source-list-item"
            :class="
              (mappingProps.modelValue || [])?.find?.(
                v_ => v_.TagName === item.TagName,
              )
                ? 'alternate-active'
                : ''
            "
            @click="handleConfirmOrDelete(item)"
          >
            <span>{{ item.TagName }}</span>
          </li>
        </ul>
      </div>
    </div>
  </LabelPrefixWraper>
</template>

<script setup>
import { useQuasar } from '@teld/q-components';
// import Chip from '@teld/q-components/Chip';
import Chip from '../chip';
import useMappingProps from 't/common/hooks/useMappingProps';
import { commonProps } from 't/common/utils';
import { computed, nextTick, ref, useAttrs, watch, onMounted } from 'vue';
import Input from '../input';
import LabelPrefixWraper from '../label-prefix-wraper';
const refComponent = ref();
const attrs = useAttrs();
// 设备是否是移动设备 isMobile => xs (此处使用xs)
const $q = useQuasar();
const isMobile = computed(() => $q.screen.xs || $q.platform.is.mobile);
const msg = ref('');
const props = defineProps({
  ...commonProps,
  ...Chip.props,
  ...LabelPrefixWraper.props,
  // 修改默认值
  clickable: {
    type: Boolean,
    default: true,
  },
  selfClickable: {
    type: [Boolean, String], // '1' ~ true, 支持点击事件(自定义点击事件); '0' ~ false 不支持点击事件 + chips 中键盘操作直接关闭
    default: false,
  },
  modelValue: {
    type: Array,
    default() {
      return undefined; // 默认值不用 []， 可以用来区分是不是初始化 undefined -> Array 类型，说明是初始化， 主要是出码时候 也要这么改
    },
  },
  readonly: {
    // removable 改为读取 readonly
    type: Boolean,
    default: false,
  },
  dataSource: {
    type: Array,
    default() {
      return [];
    },
  },
  placeholder: {
    type: String,
    default() {
      return '';
    },
  },
  // 修改默认值为 square
  square: {
    type: Boolean,
    default() {
      return false;
    },
  },
  style: [Object, String],
  asyncLoad: Boolean,
  // 这里 refresh 和 save 大小写和出码已经约定好，按规范统一为小写
  refresh: {
    type: Function,
    default() {
      return null;
    },
  },
  save: {
    type: Function,
    default() {
      return null;
    },
  },
  // 低代码传入的是 tabIndex，而非 tabindex, 就是为了覆盖前者
  tabIndex: {
    type: [String, Number],
    default() {
      return '0';
    },
  },
});
const tabIndexIconRemove = ref('');
const [mappingProps, mappingExpose] = useMappingProps(props);

// 现在出码时，取的值是小写的value
const value = computed(() => {
  return mappingProps.modelValue;
});
defineExpose({ ...mappingExpose, value });
const inDesign = ref(!!window['fas']?.inDesign);
const isDropDown = ref(true);
const listTopStyle = ref({});
const listDownStyle = ref({});
// [actions] => 动态筛选的 dataSource
const actions = ref([]);

watch(
  () => msg.value,
  (newVal, oldVal) => {
    onUpdateValue(newVal);
  },
);
watch(
  () => mappingProps.modelValue,
  (newVal, oldVal) => {
    emit('change', { newVal, oldVal });
  },
);
onMounted(() => {
  console.log(
    'refComponent?.value',
    refComponent?.value?.querySelectorAll('.q-chip__icon--remove'),
  );
  if (!!Number(mappingProps.selfClickable)) return;
  // chip 无点击行为 -- 叉号不需要要 单独搞键盘事件 -- (键盘操作整体回车即关闭)
  tabIndexIconRemove.value = '-1';
  // 可翰改好源码后，后面这个操作DOM的代码可以注销掉了
  refComponent?.value
    ?.querySelectorAll('.q-chip__icon--remove')
    .forEach(item => item.setAttribute('tabindex', -1)); // tabIndexIconRemove 改为 -1 否则 ''
});

// == 事件 ==
const emit = defineEmits(['update:modelValue', 'click', 'search', 'change']);

const handleBlur = () => {
  setTimeout(() => {
    actions.value = [];
  }, 100);
};
const handleFocus = v => {
  handleResetRemovable();
  onUpdateValue(v);
  setMenuPosition();
};
const onUpdateValue = v => {
  const arr = mappingProps.dataSource || []; // 添加 || []，兼容 studio 设计器的效果
  const arrFilter = arr?.filter?.(v_ => v_.TagName?.includes?.(v));
  actions.value = v ? arrFilter : [];
};
const handleSubmit = e => {
  e.preventDefault();
  handleConfirm({ TagName: msg.value });
  nextTick(() => {
    setMenuPosition();
  });
};
const handleConfirm = v => {
  // onConfirm
  if (!v.TagName) {
    return;
  }

  let arr = [];
  const result = mappingProps.modelValue?.find?.(
    v_ => v_.TagName === v.TagName,
  );
  if (!result) {
    arr.push(v);
  }

  arr = [].concat(mappingProps.modelValue || [], arr);
  emit('update:modelValue', arr);
  emit('search', arr);
  actions.value = [];
  msg.value = '';
};
const handleConfirmOrDelete = v => {
  // onConfirm
  if (!v.TagName) {
    return;
  }

  let arr = [];
  const result = mappingProps.modelValue?.find?.(
    v_ => v_.TagName === v.TagName,
  );
  if (!result) {
    arr.push(v);
    arr = [].concat(mappingProps.modelValue || [], arr);
  } else {
    const c = mappingProps.modelValue?.filter?.(v_ => v_.TagName !== v.TagName);
    arr = [].concat(c || []);
  }

  emit('update:modelValue', arr);
  emit('search', arr);
  actions.value = [];
  msg.value = '';
};
// 设计初衷：mobile 端节省空间；参考来源：微信的标签交互操作
// mobile 端时，即使可以 removable 默认也不展示差号，1次点击 - 此chip的removable 的差号出现，2次点击 - 才是remove
// focus 到 input 和 点击其他标签 时，removable 重置 -> false
const handleResetRemovable = () =>
  mappingProps.modelValue &&
  mappingProps.modelValue.forEach(v_ => (v_.removableForXs = false));
// 点击事件
const handleClickChip = params => {
  if (!!Number(mappingProps.selfClickable)) emit('click', params);
  if (!isMobile.value) return;
  if (params.removableForXs) {
    handleRemove(params);
  } else {
    handleResetRemovable();
    params.removableForXs = !params.removableForXs;
  }
};
const handleEnter = params => {
  if (!isMobile.value && !Number(mappingProps.selfClickable))
    handleRemove(params);
};

// handleClickAlternate 中预处理逻辑已删除，直接调用 handleConfirmOrDelete 即可
const handleClickAlternate = params => {
  handleConfirmOrDelete(params);
};
// 移除标签
const handleRemove = state => {
  const arr = [...mappingProps.modelValue];
  if (!arr || !(arr instanceof Array)) return;
  const index = arr.findIndex(item => item.TagName === state.TagName);
  if (index !== -1) {
    arr.splice(index, 1);
    emit('update:modelValue', arr);
  }
  // emit('remove', state);
};
const setMenuPosition = () => {
  // 当前焦点的元素
  // const tChips = document.querySelector('.t-chips');
  const tChips = refComponent.value;
  const heightUp = tChips?.getBoundingClientRect()?.top;
  const heightWindow = window.innerHeight;
  const heightDown = heightWindow - tChips?.getBoundingClientRect()?.bottom;
  const maxTop = heightUp * 0.9 > 400 ? 400 : heightUp * 0.9;
  const maxBottom = heightDown * 0.9 > 400 ? 400 : heightDown * 0.9;
  listDownStyle.value = {
    'z-index': 1,
    'position': 'absolute',
    'left': 0,
    'right': 0,
    'bottom': tChips?.clientHeight + 'px',
    'max-height': maxTop + 'px',
  };
  listTopStyle.value = {
    'z-index': 1,
    'position': 'absolute',
    'left': 0,
    'right': 0,
    'top': tChips?.clientHeight + 'px',
    'max-height': maxBottom + 'px',
  };
  isDropDown.value = heightDown > heightUp ? true : false;
};
</script>

<style lang="scss">
.t-chips-full-width {
  width: 100%;
}
.t-chips {
  $heightItem: 32px;
  $heightInput: 32px;
  position: relative;
  width: 100%;
  box-sizing: border-box;
  background: #fff;
  // font-family: sans-serif; // 这里全局选好一个字体后，即可删除掉，现在的默认粗体效果太差
  // padding: 0 10px; // 不需要了
  .alternate-active {
    background: #e6f2fb;
  }
  .t-chips-wrap {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    .tag-name {
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .t-chips-input {
      flex-grow: 1;
      flex-shrink: 1;
      width: 50%;
      // margin-left: 4px; // 和 chip 的样式统一
      &::placeholder {
        color: #333;
      }
      @media screen and (max-width: 767px) {
        .t-input {
          min-height: auto; // 覆盖掉 t 层的 48px;
        }
      }
    }
    // scoped 时 + deep
    // .t-chips-input ::v-deep(.q-field__control) {
    //   height: 100px; //$heightItem;;
    // }
    .t-chips-input .q-field__control {
      height: $heightInput;
    }
    // 此段挪到 chip 中 + 引用源改为 chip
    .q-chip__content {
      font-size: 14px; // 默认也是14px
    }
    // 此段挪到 chip 中 + 引用源改为 chip
    .q-chip__icon--remove {
      transform: translateX(-1px); // 修正视觉偏差
      margin-left: 6px;
      font-size: 1em;
    }
  }

  // scoped 时 + deep
  // .t-chips-wrap ::v-deep(.q-icon) {
  //   color: inherit;
  // }
  // 此段挪到 chip 中 + 引用源改为 chip
  .t-chips-wrap .q-icon {
    opacity: 1;
    color: inherit;
  }
  .data-source-list {
    color: rgba(0,0,0,0.8);
    list-style: none;
    margin: 0;
    padding: 0;
    background: #f7f8fa;
    // margin-left: 4px; // 和 chip 的样式统一
    overflow: auto;
    .data-source-list-item {
      padding: 5px 10px;
      border-bottom: 1px solid #ebedf0;
      font-size: 12px;
      &:hover {
        background: #f2f3f5;
      }
    }
  }
  .q-chip {
    border-radius: 100px;
    cursor: pointer;
  }
  // 此段可省略 挪到 chip 中 + 引用源改为 t-chip
  .q-chip {
    height: $heightItem;
    line-height: $heightItem;
    // background-color: rgba(var(--t-color-rgb), 0.1); // 0, 120, 212
    padding: 0 8px;
    // 原来是 margin-left，margin-right 都是 4px
    margin-left: 0;
    margin-right: 8px;
    // color: rgba(var(--t-color-rgb), 1); // 0, 120, 212

    padding-left: 12px;
    padding-right: 12px;
    font-size: 14px;
  }
  // 和 t-chip 不同之处
  // 有单独事件的chip 背景色为灰色 - focus / hover 才是主色系
  .q-chip {
    background: #f0f2f5;
    color: rgba(0, 0, 0, var(--t-color-opacity, /*批量处理90%透明度*/0.9));
  }
  // 分体的 - remove图标 .q-chip__icon--remove 单独算tab事件
  .q-chip.chip-pc.chip-self-clickable-true {
    &:focus {
      background-color: rgba(var(--t-color-rgb), 0.1);
      color: rgba(var(--t-color-rgb), 1);
      .q-icon {
        color: rgba(0, 0, 0, var(--t-color-opacity, /*批量处理90%透明度*/0.9));
      }
    }
    .q-icon:focus {
      color: rgba(var(--t-color-rgb), 1);
    }
    &:hover {
      background-color: rgba(var(--t-color-rgb), 0.1); // 0, 120, 212
      color: rgba(var(--t-color-rgb), 1);
      .q-icon {
        color: rgba(var(--t-color-rgb), 1);
      }
    }
    &:has(.q-icon:focus) {
      background-color: rgba(var(--t-color-rgb), 0.1);
      color: rgba(var(--t-color-rgb), 1);
    }
  }
  // 一体的 - remove图标 .q-chip__icon--remove 忽略tab事件
  .q-chip.chip-pc.chip-self-clickable-false {
    &:focus {
      background-color: rgba(var(--t-color-rgb), 0.1);
      color: rgba(var(--t-color-rgb), 1);
    }
  }
  .q-chip.chip-mobile {
    &:hover,
    &:focus {
      background-color: rgba(var(--t-color-rgb), 0.1); // 0, 120, 212
      color: rgba(var(--t-color-rgb), 1);
      .q-icon {
        color: rgba(var(--t-color-rgb), 1);
      }
    }
  }
  .q-chip.in-design {
    margin-top: 0; // 去除上下边距，studio中选中的边框和组件间无缝隙
    margin-bottom: 0;
  }

  // 去除 clickable 为 true 时的 hover 效果
  // scoped 时 + deep
  // .q-chip ::v-deep(.q-focus-helper) {
  //   width: 0;
  // }
  .q-chip .q-focus-helper {
    width: 0;
  }
}
</style>
